#pragma once
#include <iostream>
#include <jsoncpp/json/json.h>
#include <string>
#include<memory>
// 设计一下协议的报头，和报文的完整格式
// "len"\r\n"{json}"\r\n ---完整的报文 len代表有效载荷的长度

// 结构化转字符串、字符串转结构化---->序列化和反序列化
// 请求要有序列化的接口、客户端要发请求给服务器， 也要有反序列化，因为服务器也需要读到请求，然后我们做反序列化


static const std::string sep = "\r\n";
//添加报头
std::string Encode(const std::string &jsonstr)
{
    //将jsonstr编程我需要的这个："len"\r\n"{json}"\r\n
    int len = jsonstr.size();
    std::string lenstr = std::to_string(len);
    return lenstr+sep+jsonstr+sep;
}

// 不能带const
// 可能出现异常情况
// "le
// "len"
// "len"\r\n"
// "len"\r\n"{j
// "len"\r\n"{json}
// "len"\r\n"{json}"\r\n----->正常情况
// "len"\r\n"{json}"\r\n"len"\r\n"{json}"\r\n
// "len"\r\n"{json}"\r\n"len"\r\n"{json}"\r\n"len"\r\n"{json}"\r
std::string Decode(std::string &packagestream)
{
    auto pos = packagestream.find(sep);

    //无法提取到一个完整的报文，返回空串
    if(pos == std::string::npos) return std::string();
    //前闭后开：
    std::string lenstr = packagestream.substr(0, pos);
    int len = std::stoi(lenstr);
    // len代表有效载荷的长度
    int total = lenstr.size() + len + 2*sep.size();
    if(packagestream.size() < total) return std::string();
    //提取json字符串
    std::string jsonstr = packagestream.substr(pos+sep.size(), len);
    //下一次处理下一个字符串,
    packagestream.erase(0, total);
    return jsonstr;
}


class Request
{
public:
    Request()
    {}
    Request(int x, int y, char oper) : _x(x), _y(y), _oper(oper)
    {
    }
    // 客户端用序列----->目的是把结构化字段转化成一个字符串
    bool Serialize(std::string *out)
    {
        Json::Value root;
        root["x"] = _x;
        root["y"] = _y;
        root["oper"] = _oper;

        // Json::StyledWriter writer;
        Json::FastWriter writer;

        std::string s = writer.write(root);
        // std::cout << s << std::endl;
        *out = s;
        return true;
    }
    // 服务端用反序列，别人会给我传进来一个字符串，我需要将这个字符串转成结构化字段（内部属性的值
    bool Deserialize(const std::string &in)
    {
        Json::Value root;
        Json::Reader reader;
        // 传进来的字符串转换成发序列化成一个json对象
        bool res = reader.parse(in, root);
        // std::cout <
        _x = root["x"].asInt();
        _y = root["y"].asInt();
        _oper = root["oper"].asInt();
        return true;
    }
    void Print()
    {
        std::cout << _x << std::endl;
        std::cout << _y << std::endl;
        std::cout << _oper << std::endl;
    }

    int X()
    {
        return _x;
    }
    int Y()
    {
        return _y;
    }    
    char Oper()
    {
        return _oper;
    }

    void SetValue(int x, int y, char oper)
    { 
        _x = x;
        _y = y;
        _oper = oper;
    }

    ~Request()
    {
    }


private:
    int _x;
    int _y;
    char _oper; //+ 、— 、/、% //x oper y
};

// 最终相当于是服务器给客户端响应，序列化成字符串发过去，而服务器还会收需求，就可以反序列化成结构化字段
class Response
{
public:
    Response():_result(0), _code(0), _desc("success")
    {
    }
    // 客户端用序列----->目的是把结构化字段转化成一个字符串，发出去
    bool Serialize(std::string *out)
    {
        Json::Value root;
        root["result"] = _result;
        root["code"] = _code;
        root["desc"] = _desc;

        // Json::StyledWriter writer;
        Json::FastWriter writer;

        std::string s = writer.write(root);
        // std::cout << s << std::endl;
        *out = s;
        return true;
    }
    // 服务端用反序列，别人会给我传进来一个字符串，我需要将这个字符串转成结构化字段（内部属性的值
    bool Deserialize(const std::string &in)
    {
        Json::Value root;
        Json::Reader reader;
        // 传进来的字符串转换成发序列化成一个json对象
        bool res = reader.parse(in, root);
        if(!res) return false;
        _result = root["result"].asInt();
        _code = root["code"].asInt();
        _desc = root["desc"].asString();
        return true;
    }
    void Print()
    {
        std::cout << "result: " << _result << " code: " << _code << " desc: " << _desc << std::endl;
    }
    
 
    ~Response()
    {
    }

public:
    int _result;
    //状态码
    int _code; // 0:success
    //描述
    std::string _desc;
};

//工厂模式：能够直接帮我们去进行对象的创建
class Factory
{

public:
    static std::shared_ptr<Request> BuildRequestDefault()
    {
        return std::make_shared<Request>();
    }
    static std::shared_ptr<Response> BuildResponseDefault()
    {
        return std::make_shared<Response>();
    }
};